package iosu.java.games.razer.characters;

import iosu.java.games.razer.RazerClient;
import iosu.java.games.razer.Track;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;


/**
 * clase coche generica de esta heredaran los personajes del juego y cada uno
 * aportara sus caracteristicas
 * 
 * @author iosu
 * 
 */
public class Car {
	private int lapnum=1;
	// coord X inicial del centro del coche
	private int centerX = 200;
	// coord Y inicial del centro del coche
	private int centerY = 200;
	// orientacion en grados del morro del coche 0-359 en sentido horario
	private int orientation = 0;
	// si el coche esta ralentizado o no
	private boolean snared = false;

	// si el coche tiene un arma over cerca
	private boolean opweapon = false;
	// si el coche tiene un arma activa
	private boolean availweapon = false;
	// si el coche esta frenando (para ponerle lucecita roja)
	private boolean braking = false;
	// si el coche esta acelerando (para ponerle estela)
	private boolean accelerating = false;
	// si el coche esta girando
	private boolean rotatingleft = false;
	private boolean rotatingright = false;
	// estas de debajo podian ser variables de un personaje a otro
	// velocidad actual del coche
	private double currentspeed = 0;
	// velocidad maxima del coche
	private int maxspeed = 20;
	// aceleracion/freno del coche
	private int pedal = 2;
	// velocidad de giro del coche
	private int gyrospeed = 5;
	private String name;
	private int health;
	private boolean goalupdated=false;
	// cuando este coche de las vueltas que le pide el circuito, pasara a estado "finished"
	private boolean finished = false;
	
	private Image sprite;
	
	// rectangulo para la deteccion de colisiones
	private Rectangle collision;
	
	// circuito, si es distinto de null, sera el circuito sobre el que el coche esta corriendo
	// si es null, el coche no esta corriendo en ningun circuito
	private Track track;
	
	public Car(Image image, int x, int y, String name){
		this.sprite = image;
		this.centerX=x;
		this.centerY=y;
		this.name = name;
		// creo el rectangulo para las colisiones
		collision = new Rectangle(0,0,0,0);
		// empezamos con 100 de vida, vamos restando con las colisiones
		health=100;
		}

	public Image getSprite() {
		return sprite;
	}

	public void setSprite(Image sprite) {
		this.sprite = sprite;
	}

	public int getCenterX() {
		return centerX;
	}

	public void setCenterX(int centerX) {
		this.centerX = centerX;
	}

	public int getCenterY() {
		return centerY;
	}

	public void setCenterY(int centerY) {
		this.centerY = centerY;
	}

	public int getOrientation() {
		return orientation;
	}

	public void setOrientation(int orientation) {
		this.orientation = orientation;
	}

	public void update() {
		// aqui va la logica de movimiento
		// por defecto avanzo siempre hacia donde este apuntando a velocidad currentspeed
		//System.out.println("orientacion" + orientation+", velocidad "+currentspeed);
		// por el rozamiento la velocidad disminuye poco a poco
		
		if((0<currentspeed)&&(2>currentspeed)){
			currentspeed = 0;
		}else{
			currentspeed*=.95;
		}
		
		// compruebo si esta snared
		if(isSnared()){
			maxspeed = 10;
		}else{
			maxspeed = 20;
		}
		
		if(accelerating){
			accelerate();
		}
		if(braking){
			brake();
		}
		if( ((currentspeed > 3)||(currentspeed < -1)) 
				&& rotatingleft ){
			rotateLeft();
		}
		if( ((currentspeed > 3)||(currentspeed < -1)) 
				&& rotatingright){
			rotateRight();
		}
		
		// calculo la nueva posicion en funcion de la orientacion, la velocidad y la posicion actual
		double ax = Math.sin(Math.toRadians(orientation));  
		double ay = -Math.cos(Math.toRadians(orientation));
		int deltax = (int) (currentspeed*ax)/4;
		int deltay = (int) (currentspeed*ay)/4;
		//limites de la pantalla
//		if((centerX+deltax>10)&&(centerX+deltax<790)) centerX += deltax;
//		if((centerY+deltay>10)&&(centerY+deltay<470)) centerY += deltay;
		// si track es null, este no es el coche del jugador
		if(this.track==null){
			centerX += deltax;
			centerY += deltay;
		}else{
			// si el punto al que me muevo es rojo, no me muevo
			if(this.track.getColorAt(centerX+deltax, centerY+deltay)==Track.TRACK_RED){
				// si me voy a mover a un rojo, no me muevo
				
			}else{
				//  separado por x e y
				// primero x
				if(this.track.getColorAt(centerX+deltax, centerY)!=Track.TRACK_RED){
					// no es rojo, lo muevo
					if((centerX+deltax>10)&&(centerX+deltax<790)) centerX += deltax;
				}
				// despues y 
				if(this.track.getColorAt(centerX, centerY+deltay)!=Track.TRACK_RED){
					// no es rojo, lo muevo
					if((centerY+deltay>10)&&(centerY+deltay<470)) centerY += deltay;
				}
			}
			// ya he movido el coche
			// si he llegado a alguna zona amarilla, compruebo si es mi nextMilestone
			
			if((this.track.getColorAt(centerX, centerY)==Track.TRACK_YELLOW)
					||(this.track.getColorAt(centerX, centerY)==Track.TRACK_BLUE)){
				if(this.track.checkMilestone(centerX, centerY)){
					// miro si es la ultima vuelta o no
					if(this.lapnum==this.track.getNumberoflaps()){
						// este coche ha terminado la carrera
						this.finished = true;
					}else{
						//  no ha terminado, sumo otra vuelta
						this.lapnum++;
					}
				}
//				goalupdated=false;
			
			}
//			else if(this.track.getColorAt(centerX, centerY)==Track.TRACK_BLUE){
				// paso por meta.. como controlo si ya he actulizado?
//				if(this.track.checkGoal(centerX, centerY)){
//					this.lapnum++;
//					goalupdated=true;
//				}
//			}else{
//				goalupdated=false;
//			}

		}
		
		
	}
	public void update(CarStatus cs){
		this.centerX = cs.getCenterX();
		this.centerY = cs.getCenterY();
		this.currentspeed = cs.getCurrentspeed();
		this.orientation = cs.getOrientation();
		this.accelerating = cs.isAccelerating();
		this.braking = cs.isBraking();
		this.rotatingleft = cs.isRotatingLeft();
		this.rotatingright = cs.isRotatingRight();
	}
	
	public void paint(Graphics2D g, RazerClient razerClient){
		// y aplico la transformacion al sprite
		int spriteWidth = this.sprite.getWidth(null);
		int spriteHeight = this.sprite.getHeight(null);
		AffineTransform affineTransform = new AffineTransform();
		affineTransform.rotate(Math.toRadians(orientation+90), centerX + spriteWidth / 2, centerY
			            + spriteHeight / 2);
		affineTransform.translate(centerX, centerY);

	    g.drawImage(sprite, affineTransform, razerClient);
	 // rectangulo de colision
	 	collision.setBounds(this.centerX, this.centerY, 17, 18);
	 	// esto es para mostrarlo
 		g.draw(collision.getBounds2D());
	}

	// metodo que gira el coche hacia la derecha 0-360
	public void rotateRight() {
		// sumo a orientation el valor de gyrospeed * 10 (son 360 grados!!)
		if(orientation+gyrospeed>360){
			orientation = orientation+gyrospeed-360;
		}else{
			orientation += gyrospeed;
		}

	}

	// metodo que gira el coche hacia la izquierda 360-0
	public void rotateLeft() {
		// si es menor que 0, no lo hago negativo, sino resto de 360
		if(orientation-gyrospeed<0){
			orientation = 360-gyrospeed;
		}else{
			orientation -=gyrospeed;
		}
	}

	// metodo que acelera el coche
	public void accelerate() {
		accelerating = true;
		if (currentspeed + pedal <= maxspeed) {
			currentspeed += pedal;
		} else {
			// si ya voy a tope no acelero mas
		}

	}

	// metodo que frena el coche
	public void brake() {
		braking = true;
		if (currentspeed - pedal < -9) {
			// la marcha atras max. llega a -5
		} else {
			currentspeed -= pedal;
		}
	}


		

	public boolean isSnared() {
		return snared;
	}

	public void setSnared(boolean sna) {
		this.snared = sna;
	}

	public boolean isOpweapon() {
		return opweapon;
	}

	public void setOpweapon(boolean opweapon) {
		this.opweapon = opweapon;
	}

	public boolean isAvailweapon() {
		return availweapon;
	}

	public void setAvailweapon(boolean availweapon) {
		this.availweapon = availweapon;
	}

	public boolean isBraking() {
		return braking;
	}

	public void setBraking(boolean braking) {
		this.braking = braking;
	}

	public boolean isAccelerating() {
		return accelerating;
	}

	public void setAccelerating(boolean accelerating) {
		this.accelerating = accelerating;
	}


	public double getCurrentspeed() {
		return currentspeed;
	}

	public void setCurrentspeed(double currentspeed) {
		this.currentspeed = currentspeed;
	}

	public int getMaxspeed() {
		return maxspeed;
	}

	public void setMaxspeed(int maxspeed) {
		this.maxspeed = maxspeed;
	}

	public int getPedal() {
		return pedal;
	}

	public void setPedal(int pedal) {
		this.pedal = pedal;
	}

	public int getGyrospeed() {
		return gyrospeed;
	}

	public void setGyrospeed(int gyrospeed) {
		this.gyrospeed = gyrospeed;
	}

	public boolean isRotatingleft() {
		return rotatingleft;
	}

	public void setRotatingleft(boolean rotatingleft) {
		this.rotatingleft = rotatingleft;
	}

	public boolean isRotatingright() {
		return rotatingright;
	}

	public void setRotatingright(boolean rotatingright) {
		this.rotatingright = rotatingright;
	}

	public String getName() {
		return name;
	}

	public Track getTrack() {
		return track;
	}

	public void setTrack(Track track) {
		this.track = track;
	}

	public int getLapnum() {
		return lapnum;
	}

	public void setLapnum(int lapnum) {
		this.lapnum = lapnum;
	}

	public boolean isFinished() {
		return finished;
	}

	public void setFinished(boolean finished) {
		this.finished = finished;
	}
}
